/**
 * Created on 2015年9月22日 by ZhouMin
 */
package cn.hehuoren.quartz.base;

import cn.hehuoren.quartz.model.QrtzJobRunLog;
import cn.hehuoren.quartz.service.IQrtzJobRunLogService;
import cn.hehuoren.core.utils.SpringUtil;
import cn.hehuoren.core.utils.UUIDGenerator;
import cn.hehuoren.core.utils.DateUtil;
import cn.hehuoren.core.utils.StringUtil;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang.StringUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.sql.Timestamp;

/**
 * @Title 
 * @Description 
 * @Copyright Copyright (c) 2009</p>
 * @Company 源本信息科技有限公司 Co., Ltd.</p>
 * @author ZhouMin
 * @version 1.0
 * @修改记录
 * @修改序号，修改日期，修改人，修改内容
 */
public class CommonJobBean extends QuartzJobBean implements InterruptableJob{
    public static final Logger logger = LoggerFactory.getLogger(CommonJobBean.class);

    protected boolean jobInterrupted = true;
    @Resource
    private IQrtzJobRunLogService qrtzJobRunLogService;
    @Override
    public void interrupt() throws UnableToInterruptJobException {
        jobInterrupted = true;
    }
    /**
     * 任务参数
     */
    protected JobDataMap jobDataMap = null;
    /**
     * JOB名称
     */
    protected String jobName = null;
    /**
     * 要记录日志的对象
     */
     private static String logData;
    
    @Override
    protected void executeInternal(JobExecutionContext context) {
        long startTime = System.currentTimeMillis();
        Exception runException = null;
        JobKey jobKey =  context.getJobDetail().getKey();
        String jobBeanId = jobKey.getName();
        boolean enableLog = true;
        try {
            this.jobDataMap = context.getJobDetail().getJobDataMap();
            String serviceName = (String)jobDataMap.get("serviceName");
            String invokeMethod = (String)jobDataMap.get("method");
            //调度执行对应的job方法
            AutowireCapableBeanFactory beanfactory = SpringUtil.getApplicationContext().getAutowireCapableBeanFactory();
            //这里有点问题 ，如果第二个字母也是大写的时候 spring是不会把第一个字母变小写的，所以要求在配置的时候要区分大小写
//            String invokeServiceName = StringUtil.camelName(serviceName);
            logger.info("job:"+jobBeanId+"正在执行>>");
            Object jobObject = beanfactory.getBean(serviceName);
            beanfactory.autowireBean(jobObject);
            
            if(StringUtil.isEmpty(invokeMethod)){
                invokeMethod = "doExecute";
            }
            Class<?> jobClass = jobObject.getClass();
            Method[] methods = jobClass.getMethods();
            for (Method method : methods) {
                if(StringUtils.equals(method.getName(), invokeMethod)){
                    logData = null;
                    if(method.getGenericParameterTypes().length==1){
                        method.invoke(jobObject, jobDataMap);
                    }else{
                        method.invoke(jobObject);
                    }
                }
            }
        } catch (Exception e) {
            runException = e;
            e.printStackTrace();
        } finally {
            long endTime = System.currentTimeMillis();
            long runTime = endTime - startTime;
            // 记录日志-开始, 1: 默认是记录日志。 2：只要有异常就记录日志。
           if (null != runException || MapUtils.getBooleanValue(this.jobDataMap,"insertQuartzLog", true)) {
                this.inserQuartzLog(context, runException, startTime, endTime,runTime, enableLog);
           }
        }
    }
    /**
     * 追加日志, 追加的内容,将记录到数据库中
     * @param obj
     * @return
     */
    public void addQuartzLog(Object obj) {
        StringBuffer buffer = new StringBuffer();
        String time = DateUtil.getNow();
        buffer.append(time + obj);
        logData = buffer.toString();
    }
    /**
     * 记录任务日志
     * @param context
     */
    protected void inserQuartzLog(JobExecutionContext context,Exception runException, long startTime, long endTime, long runTime,
            boolean enableLog) {
        QrtzJobRunLog runlog = new QrtzJobRunLog();// 日志
        String reslog = null;
        try {
            if (enableLog) {
                if (null == runException) {
                    runlog.setRunResultCode("0000");// 日志状态码
                } else {
                    // 可根据不同的异常类型,设置不同的状态码,目前仅默认9999
                    runlog.setRunResultCode("9999");// 日志状态码
                    reslog = ExceptionUtils.getFullStackTrace(runException);
                    int loglength = reslog.length();
                    if(loglength > 50000){
                        reslog = reslog.substring(0, 49999);
                    }
                    /*if(runException instanceof java.lang.reflect.InvocationTargetException){
                        InvocationTargetException e = (InvocationTargetException)runException; 
                        reslog = String.format( "---------runException------------\r\n%s",  ExceptionUtils.getFullStackTrace(e.getTargetException())); 
                    }else{
                        reslog = String.format( "---------runException------------\r\n%s",  ExceptionUtils.getFullStackTrace(runException)); 
                    }*/
                    runlog.setRunResultDesc(reslog);// 日志描述
                }
                if (StringUtils.isNotBlank(logData)) {
                    reslog = null == runlog.getRunResultDesc() ? "" : runlog.getRunResultDesc();
                    reslog = String.format( "%s---------logData---------\n%s",logData, reslog);
                    runlog.setRunResultDesc(reslog);// 日志描述
                }
                // 记录日志-开始
                runlog.setId(UUIDGenerator.getUUID());
                runlog.setJobName(context.getJobDetail().getKey().getName());
                runlog.setJobGroup(context.getJobDetail().getKey().getGroup());
                runlog.setDescription(context.getJobDetail().getDescription());
                //runlog.setJobJsonObject(String.format("---------JobDetail------------\r\n%s",JsonUtils.obj2json(context.getJobDetail())));// 将对象序列化为JSON,并存储
                runlog.setRunStartTime(new Timestamp(startTime));
                runlog.setRunEndTime(new Timestamp(endTime));
                runlog.setRunUsedTime(runTime);// 方便查询排序
                runlog.setFireInstanceId(context.getFireInstanceId());
                qrtzJobRunLogService.insert(runlog);
            }
        } catch (Exception e2) {
            logger.error(String.format("记录任务运行日志异常, 任务名称:%s. --->  日志信息:%s --> 异常信息:", jobName, runlog), e2);
        }
    }
}
